package semantic.parser;

import exp.parser.Exp;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class VariableSymbol extends SymbolTableElement {

    private final int scope;
    private final int dimension;
    private final List<Integer> lenOfDimension;
    private final List<List<Integer>> value;
    private final List<Exp> expValue;

    public VariableSymbol(int address, SymbolType type, String ident, int scope,
                          int dimension, List<Integer> lenOfDimension, List<Integer> value, List<Exp> expValue) {
        super(address, type, ident);
        this.scope = scope;
        this.dimension = dimension;
        this.lenOfDimension = new ArrayList<>(lenOfDimension);
        this.value = new ArrayList<>();

        int y = dimension > 1 ? lenOfDimension.get(0) : 1;
        int x = dimension > 1 ? lenOfDimension.get(1) :
                dimension > 0 ? lenOfDimension.get(0) : 1;

        for (int i = 0; i < y; i++) {
            this.value.add(new ArrayList<>());
            for (int j = 0; j < x; j++) {
                int p = i * x + j;
                List<Integer> tList = this.value.get(i);
                if (value == null || value.isEmpty()) {
                    tList.add(0);
                } else {
                    int acVal = p < value.size() ? value.get(p) : 0;
                    tList.add(acVal);
                }
            }
        }


        this.expValue = expValue;
    }

    public VariableSymbol(String ident, int scope,
                          int dimension, List<Integer> lenOfDimension,
                          List<List<Integer>> value) {
        super(0, SymbolType.INT, ident);
        this.scope = scope;
        this.dimension = dimension;
        this.lenOfDimension = new ArrayList<>(lenOfDimension);
        this.value = value;
        this.expValue = null;
    }

    public int getScope() {
        return scope;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        if (!super.equals(o)) return false;
        VariableSymbol that = (VariableSymbol) o;
        return scope == that.scope;
    }

    @Override
    public int hashCode() {
        return Objects.hash(super.hashCode(), scope);
    }

    public int getDimension() {
        return dimension;
    }

    public List<Integer> getLenOfDimension() {
        return lenOfDimension;
    }

    public List<List<Integer>> getValue() {
        return value;
    }

    public List<Integer> getValue(int y) {
        return value.get(y);
    }

    public Integer getValue(int y, int x) {
        return value.get(y).get(x);
    }

    public void setValue(int value, int y, int x) {
        try {
            this.value.get(y).set(x, value);
        } catch (Exception e) {
            System.out.println(this.getIdent());
        }

    }
}
